package fr.greta.centre.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.naming.NamingException;

import fr.greta.centre.metier.Candidat;
import fr.greta.centre.metier.Candidature;
import fr.greta.centre.metier.Etat;
import fr.greta.centre.metier.Promotion;
import fr.greta.centre.metier.StagiaireEtPromo;

public class CandidatureDAOImpl implements CandidatureDAO {
	public final static int ETAT_INSCRIT = 7;
	
	
	public void inserer(Candidat candidat, Candidature candidature) throws SQLException {
		Connection connexion = null;
		  try {
			// Recuperer une connexion
			 connexion = Bd.getConnect();
			  // En faire une transaction
			  connexion.setAutoCommit(false);
		    // Inserer le candidat avec cette connexion
		    insererCandidat(candidat, connexion);// une mise a� jour du candidat puisqu'il existe
		    // Inserer la candidature avec la meme connexion
		    insererCandidature(candidature, connexion);
		    // Valider la transaction
		    connexion.commit();
		    connexion.close();
		  } catch (SQLException exc) {
		    // Annuler la transaction (les deux actions sont annullees)
		    connexion.rollback();
		    throw exc;
		 }
		}
	private void insererCandidature(Candidature candidature,
			Connection connexion) throws SQLException{
		save(candidature, connexion);
		
	}
	public void save(Candidature candidature, Connection connexion) throws SQLException {
		String sql = "INSERT INTO candidature (id_candidat, id_promotion, etat_candidature)"
				+ " VALUES(?, ?, ?)";
		PreparedStatement st;
		try {
			st = connexion.prepareStatement(sql);
			st.setInt(1, candidature.getCandidat().getId());
		    st.setInt(2, candidature.getPromotion().getIdPromotion());
		    st.setInt(3, candidature.getEtat().getIdEtat());
		    st.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			throw e;
		}
		
		
	}
	private void insererCandidat(Candidat candidat, Connection connexion) throws SQLException{
		CandidatDAOImpl dao=new CandidatDAOImpl();
		dao.save(candidat, connexion);
		
	}
	/** Sauver candidature pour un candidat existant */
	@Override
	public int save(Candidature candidature) throws SQLException {
		{
			throw new SQLException("Not yet implemented");
		}
	}

	/*
	public int saveSiCandidatConnu(Candidature candidature) throws SQLException {
		Connection connexion = Bd.getConnect();
		// En faire une transaction
		connexion.setAutoCommit(false);
		try {
			saveSansTransaction(candidature, connexion);
			CandidatDAO dao = new CandidatDAOImpl();
			dao.saveSansTransaction(candidature.getCandidat(), connexion);
			connexion.commit();
		} catch (SQLException exc) {
			connexion.rollback();
			throw exc;
		}
		return 0;
	}
	*/
	
	public int saveSansTransaction(Candidature t, Connection connexion) throws SQLException {
		String sql = "INSERT INTO candidature (id_candidat, id_promotion, etat_candidature)"
				+ " VALUES(?, ?, ?)";
		PreparedStatement st = connexion.prepareStatement(sql);
		st.setInt(1, t.getCandidat().getId());
		st.setInt(2, t.getPromotion().getIdPromotion());
		st.setInt(3, t.getEtat().getIdEtat());
		st.executeUpdate();
		connexion.close();
		return 0;
		
	}

	/** Sauver candidature + candidat */
	@Override
	public int saveCandidatNouveau(Candidature candidature) throws SQLException {
		assert candidature.getCandidat() != null;
		Connection connection =null;
		
		try {
			// Inserer le candidat et la candidature en 1 transaction
			connection = Bd.getConnect();
			// On fait une transaction
			connection.setAutoCommit(false);
			CandidatDAO dao = new CandidatDAOImpl();
			dao.save(candidature.getCandidat());
			save(candidature);
			connection.commit();
			
		} catch (SQLException exc) {
			System.out.println(exc.getMessage());
			connection.rollback();
			throw exc;
		}
		connection.close();
		return 0;
	}

	@Override
	public boolean delete(int id_candidat, int idPromotion) {
		String sql = "DELETE FROM candidature WHERE id_candidat = ?, AND id_promotion = ?,";
		PreparedStatement st;
		try {
			st = Bd.getConnect().prepareStatement(sql);
			st.setInt(1, id_candidat);
			st.setInt(2, idPromotion);
			st.execute();
			st.getConnection().close();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	
	public Candidature findByKey(int id_candidat) throws SQLException {
		
		
		try {
			Connection conn = Bd.getConnect();
			Statement st = conn.createStatement();
			String sql = "SELECT id_candidat"
					+ "FROM candidat INNER JOIN candidature ON candidat.id_candidat = candidature.id_candidat "
					+ "WHERE id_candidat =" + id_candidat;
			ResultSet rs = st.executeQuery(sql);
			
			if (rs.next()) {
				
				//@SuppressWarnings("unchecked")
				List<Candidature> lesCandidatures = (List<Candidature>)new CandidatDAOImpl().findByKey(rs.getInt("candidat.id_candidat"));
				rs = (ResultSet) new Candidature();
				
				
			} 
			conn.close();
		}
		catch (SQLException e) {

			throw e;
		}
		return null;
	}

	@Override
	public List<Candidature> findAll() throws SQLException {
		List<Candidature> lesCandidatures = new ArrayList<Candidature>();
		try {
			Connection connect = Bd.getConnect();
			String sql = "SELECT * FROM candidature ";
			ResultSet resultat;

			resultat = connect.createStatement().executeQuery(sql);
			while (resultat.next()) {
				Candidat unCandidat = new Candidat();
				unCandidat.setId(resultat.getInt("id_candidat"));
				Promotion unePromotion = new Promotion();
				unePromotion.setIdPromotion(resultat.getInt("id_promotion"));
				Etat unEtat = new Etat();
				unEtat.setIdEtat(resultat.getInt("id_etat"));
				Candidature uneCandidature = new Candidature();
				uneCandidature.setCandidat(unCandidat);
				uneCandidature.setEtat(unEtat);
				uneCandidature.setPromotion(unePromotion);
				lesCandidatures.add(uneCandidature);
			}
			connect.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return lesCandidatures;

	}

	@Override
	public ArrayList<Candidature> findByIdPersonne(int idPersonne) {
		ArrayList<Candidature> lesCandidatures = new ArrayList<Candidature>();

		try {
			Statement st = Bd.getConnect().createStatement();
			String sql = "SELECT * FROM candidature" +
					" WHERE id_candidat = " + idPersonne;
			ResultSet rs = st.executeQuery(sql);
			
			CandidatDAOImpl candidatDAO = new CandidatDAOImpl(); 
			Candidat leCandidat = candidatDAO.findByKey(idPersonne);
			
			while(rs.next()) {
				PromotionDAOImpl unePromotionDAO = new PromotionDAOImpl();
				Promotion unePromotion = unePromotionDAO.findByKey(rs.getInt("id_promotion"));
				
				EtatDAOImpl etatDAO = new EtatDAOImpl();
				Etat unEtat = etatDAO.findByKey(rs.getInt("etat_candidature"));
				
				Candidature uneCandidature = new Candidature(leCandidat, unePromotion, unEtat);
				lesCandidatures.add(uneCandidature);
				
			}
			st.getConnection().close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return lesCandidatures;
	}
	
	public List<Candidature> findByIdPromotion(int idPromotion){
		ArrayList<Candidature> lesCandidatures = new ArrayList<Candidature>();
		String sql = "SELECT * FROM candidature WHERE id_promotion = ?";
		try {
			PreparedStatement st = Bd.getConnect().prepareStatement(sql);
			st.setInt(1, idPromotion);
			ResultSet rs = st.executeQuery();
			
			while( rs.next() ) {
				Candidat unCandidat = new CandidatDAOImpl().findByKey(rs.getInt("id_candidat"));
				Promotion unePromotion = new PromotionDAOImpl().findByKey(idPromotion);
				Etat unEtat = new EtatDAOImpl().findByKey(rs.getInt("etat_candidature"));
				Candidature uneCandidature = new Candidature(unCandidat, unePromotion, unEtat);
				lesCandidatures.add(uneCandidature);
				
			}
			st.getConnection().close();
			return lesCandidatures;
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}

	@Override
	public boolean delete(int id) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}
	@Override
	public void mettreAjour(Candidat candidat, Candidature candidature)
			throws SQLException {
		Connection connexion = null;
		  try {
			  // Recuperer une connexion
			  connexion = Bd.getConnect();
			  // En faire une transaction
			  connexion.setAutoCommit(false);
		    // Inserer le candidat avec cette connexion
		    mettreAjourCandidat(candidat, connexion);// une mise à jour du candidat puisqu'il existe
		    // Inserer la candidature avec la meme connexion
		    insererCandidature(candidature, connexion);
		    // Valider la transaction
		    connexion.commit();
		    connexion.close();
		  } catch (SQLException exc) {
		    // Annuler la transaction (les deux actions sont annullees)
		    throw exc;
		 }
		
	}
	private void mettreAjourCandidat(Candidat candidat, Connection connexion) throws SQLException{
		CandidatDAOImpl daoImpl = new CandidatDAOImpl();
		daoImpl.mettreAjour(candidat, connexion);
		
	}
	
	// On suppose qu'un candidat ne peut candidater pour un cursus donn� qu'une seule fois par promotion 
	// cette m�thode est appel�e par la servlet PDFCandidatureServlet charg�e de g�n�rer une vue pdf de la candidature
	public Candidature findByCandidatAndPromotion(int idCandidat, int idPromotion) throws SQLException{
		CandidatDAO daoCandidat =new CandidatDAOImpl();
		PromotionDAOImpl daoPromotion = new PromotionDAOImpl();
		Etat unEtat = new Etat(); 
		Candidature uneCandidature =null;
		String sql= "SELECT * FROM candidature WHERE id_candidat = "+idCandidat+" AND id_promotion = "+idPromotion;
		Statement st;		
		try {
			
			Promotion unePromotion = daoPromotion.findByKey(idPromotion);
			Candidat unCandidat =daoCandidat.findByKey(idCandidat);
			st = Bd.getConnect().createStatement();
			ResultSet rs=st.executeQuery(sql);
			if(rs.next()){
			unEtat.setIdEtat(rs.getInt("etat_candidature"));
			uneCandidature = new Candidature(unCandidat, unePromotion, unEtat);
			uneCandidature.setDateEffet(rs.getDate("date_effet")); 
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw e;
		}
		
		return uneCandidature;
	}
	public List<StagiaireEtPromo> getStagiairesByIdPromotion(int idPromotion) throws NamingException {
		List<StagiaireEtPromo> stagiaires = new ArrayList<StagiaireEtPromo>();
		String sql = "select * from candidature "
				+ "inner join candidat on candidature.id_candidat = candidat.id_candidat "
				+ "where id_promotion = " + idPromotion + " and etat_candidature = " + ETAT_INSCRIT;
		System.out.println(sql);
		StagiaireEtPromo stagiaire;
		try {
			PreparedStatement st = Bd.getConnect().prepareStatement(sql);
			//st.setInt(1, idPromotion);
			ResultSet rs = st.executeQuery();
			while (rs.next()) {
				stagiaire = new StagiaireEtPromo();
				stagiaire.setIdPromotion(rs.getInt("id_promotion"));
				stagiaire.setNom(rs.getString("nom"));
				stagiaire.setPrenom(rs.getString("prenom"));
				stagiaire.setAdresse(rs.getString("adresse"));
				stagiaire.setCp(rs.getString("cp"));
				stagiaire.setVille(rs.getString("ville"));
				stagiaires.add(stagiaire);
			}
		}
		catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return stagiaires;
	}
  public int updatePromoCandidature(int idCandidat, int idNouvellePromo,
                        int idPromoActuelle) throws SQLException {
               
               
                try {
                                String sql = "UPDATE centre_formation.candidature SET id_promotion=? WHERE id_candidat=? AND id_promotion=?";

                                Connection conn = Bd.getConnect();

                                PreparedStatement st = conn.prepareStatement(sql);

                                st.setInt(1, idNouvellePromo);
                                st.setInt(2, idCandidat);
                                st.setInt(3, idPromoActuelle);
                               

                                st.executeUpdate();

                                return 1;
                        }
                        catch (SQLException e) {
                                System.out.println(e.getMessage());
                                throw e;
                        }
        }

	
}
